import logging
import json

import paho.mqtt.client as mqtt
from settings import MQTT_HOST, MQTT_PORT, MQTT_USERNAME, MQTT_PASSWORD
import psycopg2.extras
from database import db_pool_singleton
from database.receive_rfid_tool_box_info_table_methods import ReceiveRfidToolBoxInfoTableMethods


# logger = logging.getLogger(__name__)

# logger.setLevel(logging.DEBUG)

# file_handler = logging.FileHandler('mqtt_service.log', encoding='utf-8')

# file_handler.setLevel(logging.DEBUG)

# formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# file_handler.setFormatter(formatter)

# logger.addHandler(file_handler)
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

logger = logging.getLogger(__name__)

class MQTTService:
    def __init__(self, host, port, username, password):
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.client = mqtt.Client()
        self.client.on_connect = self.on_connect
        self.client.on_message = self.on_message


    def on_connect(self, client, userdata, flags, rc):
        logger.info("mqtt connected with result code " + str(rc))
        # self.send_message("rfid/toolbox/rx", {"task_type": "hello_world"})
        client.subscribe("rfid/toolbox/rx")


    def on_message(self, client, userdata, msg):

        # print(f"mqtt receive message {msg.topic} {str(msg.payload)}")
        logger.debug(f"mqtt receive topic {msg.topic} ")

        logger.debug(f"mqtt receive message：{str(msg.payload)}")

        try:
            parse_msg = json.loads(msg.payload.decode().replace("'", '"'))

        except Exception as e:

            logger.error(f"mqtt receive message parse error：{e}")

            return
        else:

            logger.debug(f"mqtt receive message after parse：{parse_msg}")
       
        if not isinstance(parse_msg, dict) :

            logger.error("parse_msg is not a dict")

        elif parse_msg.get("task_type") == 'inventory_data':

            self.on_message_task_type_is_inventory_data(parse_msg)

        elif parse_msg.get("task_type") == 'GPS':

            self.on_message_task_type_is_GPS(parse_msg)

    
    def on_message_task_type_is_inventory_data(self, parse_msg):
        '''\
        :param parse_msg: {
            "task_type": "inventory_data",
            "mac": "xxxxxxxx", # 设备唯一标识码
            "task_sn": "yyyyyyyy", # 任务唯一标识码
            "task_data": {
                "tag_list": ["000001", "000002","000003","000004","000005","000006"],
                "data_num": "1/5"
            }
        }'''


        with db_pool_singleton.getconn() as conn:

            cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)

            rfid_tool_box_info_table_methods = ReceiveRfidToolBoxInfoTableMethods(conn, cur)

            rfid_tool_box_info_table_methods.insert_rfid_tool_box_info(
                parse_msg['mac'], 
                parse_msg['task_type'], 
                parse_msg['task_sn'], 
                json.dumps(parse_msg['task_data'])
            )


        logger.debug(f"mqtt receive inventory data message insert into database success")

    def on_message_task_type_is_GPS(self, parse_msg):
        '''\
        :param parse_msg: {
            'task_type':'GPS',
            'mac':'xxxxxxxx',
            'task_sn':'yyyyyyyy',
            'task_data':{'longitude':'11657.91323,E','latitude':'3943.38340,N'}
        }
        '''
        with db_pool_singleton.getconn() as conn:

            cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)

            rfid_tool_box_info_table_methods = ReceiveRfidToolBoxInfoTableMethods(conn, cur)

            rfid_tool_box_info_table_methods.insert_rfid_tool_box_info(
                parse_msg['mac'], 
                parse_msg['task_type'], 
                parse_msg['task_sn'], 
                json.dumps(parse_msg['task_data'])
            )

        logger.debug(f"mqtt receive GPS message insert into database success")


    def connect(self):
        self.client.username_pw_set(self.username, self.password)
        self.client.connect(self.host, self.port, 60)
        self.client.loop_forever()



    def disconnect(self):
        self.client.loop_stop()
        self.client.disconnect()


    def send_message(self, topic ,message):
        self.client.publish(topic, json.dumps(message))

    
if __name__ == '__main__':

    logger.setLevel(logging.DEBUG)

    mqtt_service = MQTTService(MQTT_HOST, MQTT_PORT, MQTT_USERNAME, MQTT_PASSWORD)
    mqtt_service.connect()
